package com.conversationboard.model.preferences;

import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.TimeZone;

import com.conversationboard.database.Database;
import com.conversationboard.database.Queries;
import com.conversationboard.model.User;
import com.conversationboard.serialisation.XmlSerialiser;

public class UserPreferences {

	private transient User user;
	private transient TimeZone timeZone = TimeZone.getTimeZone("GMT");

	private boolean showImages = true;
	private boolean displayRelativeTimes = true;
	private boolean showBookmarksOnMainPages = false;
	private String timeZoneString = "GMT";
	private boolean hideThreadInfo = false;
	private boolean hidePolls = false;
	private boolean hideTimeDisplay = false;
	private Map<Integer, SiteNewPostsViewInfo> siteNewPostsViewInfo = new HashMap<Integer, SiteNewPostsViewInfo>(23);
	private boolean useBoardShortcuts = false;
	private List<Integer> boardShortcuts = new ArrayList<Integer>();
	private boolean useTraditionalBookmarks = false;
	private boolean hideLastUpdatedBy = false;

	/* These properties are redundant. They are here to ensure that when loaded that deserialisation of an existing user's
	 * preferences don't fail. In time, rewriting them ought to remove it. */

	private transient boolean displayLastUpdatedBy = true;
	private transient boolean hideAdminMenu = false;


	public boolean isDisplayLastUpdatedBy() {
		return displayLastUpdatedBy;
	}


	public void setDisplayLastUpdatedBy(boolean displayLastUpdatedBy) {
		this.displayLastUpdatedBy = displayLastUpdatedBy;
	}


	public boolean isHideLastUpdatedBy() {
		return hideLastUpdatedBy;
	}


	public void setHideLastUpdatedBy(boolean hideLastUpdatedBy) {
		this.hideLastUpdatedBy = hideLastUpdatedBy;
	}


	public boolean isUseTraditionalBookmarks() {
		return useTraditionalBookmarks;
	}


	public void setUseTraditionalBookmarks(boolean useTraditionalBookmarks) {
		this.useTraditionalBookmarks = useTraditionalBookmarks;
	}


	public boolean isUseBoardShortcuts() {
		return useBoardShortcuts;
	}


	public void setUseBoardShortcuts(boolean useBoardShortcuts) {
		this.useBoardShortcuts = useBoardShortcuts;
	}


	public List<Integer> getBoardShortcuts() {

		if (boardShortcuts == null) {
			this.boardShortcuts = new ArrayList<Integer>();
		}

		return boardShortcuts;
	}


	public void setBoardShortcuts(List<Integer> boardShortcuts) {
		this.boardShortcuts = boardShortcuts;
	}


	public void restoreDefaultSiteNewPostsView() throws SQLException {
		siteNewPostsViewInfo = new HashMap<Integer, SiteNewPostsViewInfo>(23);
		this.store();
	}


	public Map<Integer, SiteNewPostsViewInfo> getSiteNewPostsViewInfo() {
		return siteNewPostsViewInfo;
	}


	public void setSiteNewPostsViewInfo(Map<Integer, SiteNewPostsViewInfo> siteNewPostsViewInfo) {
		this.siteNewPostsViewInfo = siteNewPostsViewInfo;
	}


	public boolean isHideAdminMenu() {
		return hideAdminMenu;
	}


	public void setHideAdminMenu(boolean hideAdminMenu) {
		this.hideAdminMenu = hideAdminMenu;
	}


	public static UserPreferences load(User user, String preferencesXml) {

		XmlSerialiser<UserPreferences> serialiser = new XmlSerialiser<UserPreferences>();
		serialiser.omitField(UserPreferences.class, "hideAdminMenu");
		serialiser.setAlias("Preferences", UserPreferences.class);

		UserPreferences preferences = serialiser.deSerialise(preferencesXml);
		preferences.setUser(user);
		preferences.initialise();

		return preferences;

	}


	void setUser(User user) {
		this.user = user;
	}


	private void initialise() {

		if (this.getTimeZoneString() == null) {
			this.setTimeZone(TimeZone.getTimeZone("GMT"));
		} else {
			this.setTimeZone(TimeZone.getTimeZone(this.getTimeZoneString()));
		}

	}


	/**
	 * If you've already got a connection, use this method (since tables may be locked).
	 * 
	 * @param connection
	 * @throws SQLException
	 */

	public void store(Connection connection) throws SQLException {

		XmlSerialiser<UserPreferences> serialiser = new XmlSerialiser<UserPreferences>();
		serialiser.setAlias("Preferences", UserPreferences.class);
		String xml = serialiser.serialise(this);

		PreparedStatement statement = connection.prepareStatement(Queries.UPDATE_PREFERENCES);
		statement.setString(1, xml);
		statement.setString(2, user.getLoginId());

		statement.executeUpdate();

		statement.close();

	}


	public void store() throws SQLException {

		/* Transform this object into an XML document */

		XmlSerialiser<UserPreferences> serialiser = new XmlSerialiser<UserPreferences>();
		serialiser.setAlias("Preferences", UserPreferences.class);
		String xml = serialiser.serialise(this);

		/* Store this document in the database */

		Connection connection = null;

		try {
			connection = Database.getConnection();

			PreparedStatement statement = connection.prepareStatement(Queries.UPDATE_PREFERENCES);
			statement.setString(1, xml);
			statement.setString(2, user.getLoginId());

			statement.executeUpdate();

			statement.close();

		} finally {
			Database.close(connection);
		}

	}


	public TimeZone getTimeZone() {
		return timeZone;
	}


	public void setTimeZone(TimeZone timeZone) {
		this.timeZone = timeZone;
		this.timeZoneString = this.timeZone.getID();
	}


	public UserPreferences(User user) {
		this.user = user;
	}


	public String getTimeZoneString() {
		return timeZoneString;
	}


	public void setTimeZoneString(String timeZoneString) {
		this.timeZoneString = timeZoneString;
		this.timeZone = TimeZone.getTimeZone(timeZoneString);
	}


	public boolean isDisplayRelativeTimes() {
		return displayRelativeTimes;
	}


	public void setDisplayRelativeTimes(boolean displayRelativeTimes) {
		this.displayRelativeTimes = displayRelativeTimes;
	}


	public boolean isShowImages() {
		return showImages;
	}


	public void setShowImages(boolean showImages) {
		this.showImages = showImages;
	}


	public boolean isShowBookmarksOnMainPages() {
		return showBookmarksOnMainPages;
	}


	public void setShowBookmarksOnMainPages(boolean showBookmarksOnMainPages) {
		this.showBookmarksOnMainPages = showBookmarksOnMainPages;
	}


	public boolean isHideThreadInfo() {
		return hideThreadInfo;
	}


	public void setHideThreadInfo(boolean hideThreadInfo) {
		this.hideThreadInfo = hideThreadInfo;
	}


	public boolean isHidePolls() {
		return hidePolls;
	}


	public void setHidePolls(boolean hidePolls) {
		this.hidePolls = hidePolls;
	}


	public boolean isHideTimeDisplay() {
		return hideTimeDisplay;
	}


	public void setHideTimeDisplay(boolean hideTimeDisplay) {
		this.hideTimeDisplay = hideTimeDisplay;
	}

}
